//
//  YHPropertyWrapper.swift
//  YHKit
//
//  Created by amovision on 2025/8/6.
//

import Foundation

@propertyWrapper
public class Atomic<Value> {
  private var lock: NSRecursiveLock = .init()

  private var value: Value

  public var wrappedValue: Value {
    get {
      lock.lock(); defer { lock.unlock() }
      return value
    }

    set {
      lock.lock(); defer { lock.unlock() }
      value = newValue
    }
  }

  public init(wrappedValue value: Value) {
    self.value = value
  }
}

@propertyWrapper
public class YHUserDefault<T: Codable> {
  public let key: String
  private var value: T? = nil

  public init(_ key: String) {
    self.key = key
  }

  public var wrappedValue: T? {
    get {
      if value != nil { return value }
      if let data = UserDefaults.standard.data(forKey: key) {
        value = (try? JSONDecoder().decode(T.self, from: data))
      }
      return value
    }
    set {
      if let newValue {
        if let data = try? JSONEncoder().encode(newValue) {
          UserDefaults.standard.set(data, forKey: key)
        }
      } else {
        UserDefaults.standard.removeObject(forKey: key)
      }
      value = newValue
    }
  }
}

// 内部使用类存储状态（引用类型避免可变性问题）

// 简洁的属性包装器实现
@propertyWrapper
public struct OnceAssignable<T> {
  private class Storage {
    var value: T
    var hasBeenAssigned = false

    init(initialValue: T) {
      self.value = initialValue
    }
  }

  private let storage: Storage

  public init(wrappedValue: T) {
    self.storage = Storage(initialValue: wrappedValue)
  }

  public var wrappedValue: T {
    get { storage.value }
    set {
      if !storage.hasBeenAssigned {
        storage.value = newValue
        storage.hasBeenAssigned = true
      }
    }
  }

  // 投影值暴露重置方法
  public var projectedValue: Self { self }

  // 重置方法（不需要mutating，因为storage是引用类型）
  public func reset() {
    storage.hasBeenAssigned = false
  }
}

